1
2
3
4 package joeq.Class;
5
6 import java.util.Iterator;
7 import java.util.LinkedList;
8 import java.util.List;
9 import joeq.Allocator.CodeAllocator;
10 import joeq.Allocator.DefaultHeapAllocator;
11 import joeq.Assembler.DirectBindCall;
12 import joeq.Bootstrap.BootstrapCodeAddress;
13 import joeq.Bootstrap.BootstrapHeapAddress;
14 import joeq.Compiler.CompilerInterface;
15 import joeq.Main.jq;
16 import joeq.Memory.CodeAddress;
17 import joeq.Memory.HeapAddress;
18 import joeq.Memory.StackAddress;
19 import joeq.Runtime.Debug;
20 import joeq.Runtime.ExceptionDeliverer;
21 import jwutil.collections.Filter;
22 import jwutil.collections.Pair;
23
24 /***
25 * Delegates
26 *
27 * @author Michael Martin <mcmartin@stanford.edu>
28 * @version $Id: Delegates.java 1941 2004-09-30 03:37:06Z joewhaley $
29 */
30 public class Delegates implements jq_ClassFileConstants {
31 static class Field implements jq_Field.Delegate {
32 public final boolean isCodeAddressType(jq_Field f) {
33 return f.getType() == CodeAddress._class ||
34 f.getType() == BootstrapCodeAddress._class;
35 }
36 public final boolean isHeapAddressType(jq_Field f) {
37 return f.getType() == HeapAddress._class ||
38 f.getType() == BootstrapHeapAddress._class;
39 }
40 public final boolean isStackAddressType(jq_Field f) {
41 return f.getType() == StackAddress._class;
42 }
43 }
44 static class Method implements jq_Method.Delegate {
45 public final jq_CompiledCode compile_stub (jq_Method m) {
46 return default_compiler.generate_compile_stub(m);
47 }
48 public final jq_CompiledCode compile (jq_Method m) {
49 jq_CompiledCode default_compiled_version;
50
51 if (m.isNative() && m.getBytecode() == null) {
52 System.out.println("Unimplemented native method! "+m);
53 if (ExceptionDeliverer._nativeMethodError.getState() < STATE_CLSINITIALIZED) {
54 jq_Class k = ExceptionDeliverer._class;
55 k.verify();
56 if (ExceptionDeliverer._nativeMethodError.getState() != STATE_PREPARED)
57 ExceptionDeliverer._nativeMethodError.prepare();
58 default_compiled_version = ExceptionDeliverer._nativeMethodError.compile();
59
60 } else {
61 default_compiled_version = ExceptionDeliverer._nativeMethodError.getDefaultCompiledVersion();
62 }
63 } else if (m.isAbstract()) {
64 if (ExceptionDeliverer._abstractMethodError.getState() < STATE_CLSINITIALIZED) {
65 jq_Class k = ExceptionDeliverer._class;
66 k.verify();
67
68 if (ExceptionDeliverer._abstractMethodError.getState() != STATE_PREPARED)
69 ExceptionDeliverer._abstractMethodError.prepare();
70 default_compiled_version = ExceptionDeliverer._abstractMethodError.compile();
71
72 } else {
73 default_compiled_version = ExceptionDeliverer._abstractMethodError.getDefaultCompiledVersion();
74 }
75 } else {
76 CompilerInterface compiler = getCompiler(m);
77 default_compiled_version = compiler.compile(m);
78 if (jq.RunningNative)
79 default_compiled_version.patchDirectBindCalls();
80 }
81 return default_compiled_version;
82 }
83 }
84 public static CompilerInterface default_compiler;
85 public static List compilers = new LinkedList();
86 public static CompilerInterface getCompiler(String name) {
87 try {
88 Class c = Class.forName(name);
89 return (CompilerInterface) c.newInstance();
90 } catch (Exception x) {
91 System.err.println("Error occurred while instantiating compiler "+name);
92 x.printStackTrace();
93 return null;
94 }
95 }
96 public static void setDefaultCompiler(String name) {
97 CompilerInterface c = getCompiler(name);
98 if (c == null) c = getCompiler("joeq.Compiler.Reference.x86.x86ReferenceCompiler.Factory");
99 default_compiler = c;
100 }
101 public static void registerCompiler(Filter f, CompilerInterface c) {
102 compilers.add(0, new Pair(f, c));
103 }
104 public static CompilerInterface getCompiler(jq_Method m) {
105 for (Iterator i=compilers.iterator(); i.hasNext(); ) {
106 Pair p = (Pair) i.next();
107 Filter f = (Filter) p.get(0);
108 if (f.isElement(m))
109 return (CompilerInterface) p.get(1);
110 }
111 return default_compiler;
112 }
113
114 static class CompiledCode implements jq_CompiledCode.Delegate {
115 public void patchDirectBindCalls (Iterator i) {
116 while (i.hasNext()) {
117 DirectBindCall r = (DirectBindCall) i.next();
118 r.patch();
119 }
120 }
121 public void patchDirectBindCalls (Iterator i, jq_Method method, jq_CompiledCode cc) {
122 while (i.hasNext()) {
123 DirectBindCall r = (DirectBindCall) i.next();
124 if (r.getTarget() == method) {
125 if (jq_CompiledCode.TRACE_REDIRECT) Debug.writeln("patching direct bind call in " + this + " at " + r.getSource().stringRep() + " to refer to " + cc);
126 r.patchTo(cc);
127 }
128 }
129 }
130 public Iterator getCompiledMethods() {
131 return CodeAllocator.getCompiledMethods();
132 }
133 public final void deliverToStackFrame(Object ed, jq_CompiledCode t, Throwable x, jq_TryCatch tc, CodeAddress entry, StackAddress fp) {
134 ((ExceptionDeliverer)ed).deliverToStackFrame(t, x, tc, entry, fp);
135 }
136 public final Object getThisPointer(Object ed, jq_CompiledCode t, CodeAddress ip, StackAddress fp) {
137 return ((ExceptionDeliverer)ed).getThisPointer(t, ip, fp);
138 }
139 }
140
141 static class Klass implements jq_Class.Delegate {
142 public final Object newInstance(jq_Class c, int instance_size, Object vtable) {
143 c.cls_initialize();
144 return DefaultHeapAllocator.allocateObject(instance_size, vtable);
145 }
146 }
147 static class Array implements jq_Array.Delegate {
148 public final Object newInstance(jq_Array a, int length, Object vtable) {
149 return DefaultHeapAllocator.allocateArray(length, a.getInstanceSize(length), vtable);
150 }
151 }
152 }